package jp.cane.android.luciferblue;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ParseException;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.text.format.Time;
import android.util.Log;

public class MainService extends Service implements LocationListener {
	final static private int registerPeriod = 5 * 60 * 1000;
	// final static private String postUrl =
	// "http://www.luciferblue.net/member/put.php/?user=1702";
	final static private String postUrl = "http://cloudcande.project2108.com/injection/put.php?user=1702";

	static protected BluetoothDevice device = null;

	protected static String username = "";
	protected static String password = "";

	protected static String pollingStrings;
	protected static int pollingInterval;
	protected static boolean pollingLoop;

	protected Thread pollingThread = null;

	private MainThread thread = null;
	private Timer timer = null;
	private LocationManager locationManager = null; // ロケーションマネージャ

	static protected int sn = 0;
	static protected Calendar lastUpTime = null;
	private Location lastLocation = null;

	private ArrayList<MainServiceListener> listener = new ArrayList<MainService.MainServiceListener>();

	public interface MainServiceListener {
		public void change(String str);
	}

	// サービスに接続するためのBinder
	public class MainServiceBinder extends Binder {
		// サービスの取得
		public MainService getService() {
			return MainService.this;
		}
	}

	// Binderの生成
	private final IBinder mBinder = new MainServiceBinder();

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	public void addListener(MainServiceListener listener) {
		// System.out.println("add Listener: " + listener.getClass().getName());
		this.listener.add(listener);
	}

	public void removeListener(MainServiceListener listener) {
		this.listener.remove(listener);
	}

	@Override
	public void onCreate() {
		// System.out.println("Luciferblue Service start.");
		this.thread = new MainThread(this);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
	}

	public void startBackground() {
		Intent intent = new Intent(this, MainActivity.class);
		PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
		Notification notification = new Notification(R.drawable.icon,
				getResources().getString(R.string.app_name),
				System.currentTimeMillis());
		notification.setLatestEventInfo(this,
				getResources().getString(R.string.app_name), getResources()
						.getString(R.string.app_name), pi);
		startForeground(1, notification);

		// ロケーションマネージャのインスタンスを取得する
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

		// 位置情報の更新を受け取るように設定
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, // プロバイダ
				0, // 通知のための最小時間間隔
				0, // 通知のための最小距離間隔
				this); // 位置情報リスナー

		this.timer = new Timer(false);
		this.timer.scheduleAtFixedRate(new TimerTask() {
			@Override
			public void run() {
				registerData();
			}
		}, new Date((System.currentTimeMillis() + 2 * registerPeriod - 1)
				/ registerPeriod * registerPeriod), registerPeriod);
	}

	public void stopBackground() {
		if (this.timer != null) {
			this.timer.cancel();
			this.timer = null;
		}
		// 位置情報の更新を止める
		if (locationManager != null) {
			locationManager.removeUpdates(this);
		}
	}

	public void startPolling() {
		if (pollingThread != null && pollingThread.isAlive()) {
			return;
		}
		pollingThread = new Thread() {
			public void run() {
				String[] strs = pollingStrings.split("\n");
				do {
					for (String str : strs) {
						if (str != strs[0]) {
							try {
								Thread.sleep(pollingInterval * 1000);
							} catch (InterruptedException e) {
							}
						}
						if (pollingThread == null) {
							return;
						}
						getThread().send(str, MainActivity.echo);
					}
					if (pollingLoop) {
						try {
							Thread.sleep(pollingInterval * 1000);
						} catch (InterruptedException e) {
						}
					}
				} while (pollingLoop);
			};
		};
		// polling.setChecked(true);
		pollingThread.start();
	}

	public void stopPolling() {
		if (pollingThread != null && pollingThread.isAlive()) {
			pollingThread.interrupt();
			pollingThread = null;
		}
	}

	public MainThread getThread() {
		return this.thread;
	}

	public void change(String str) {
		for (MainServiceListener listener : this.listener) {
			listener.change(str);
		}
	}

	public void send(String str, boolean echo) {
		if (this.thread != null) {
			this.thread.send(str, echo);
		}
	}

	private void appendToLog(String str) {
		try {
			File file = new File(Environment.getExternalStorageDirectory(),
					"luciferblue/imaocande.log");
			// Log.d("luciferblue", "Append log: " + file.toString());
			if (!file.exists()) {
				file.getParentFile().mkdirs();
				file.createNewFile();
			}
			OutputStream os = new FileOutputStream(file, true);
			os.write(str.getBytes());
			os.write('\n');
			os.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void sendDataToServer(String str) {
		DefaultHttpClient httpClient = new DefaultHttpClient();
		try {
			// POST Requestを構築する。
			HttpPost request = new HttpPost(postUrl);
			// リクエストパラメータの設定
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			params.add(new BasicNameValuePair("data", str));
			// POST データの設定
			request.setEntity(new UrlEncodedFormEntity(params));
			// 認証情報の設定
			UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
					"red", "light");
			AuthScope scope = new AuthScope(request.getURI().getHost(), request
					.getURI().getPort());
			httpClient.getCredentialsProvider().setCredentials(scope,
					credentials);

			httpClient.execute(request, new ResponseHandler<String>() {
				public String handleResponse(HttpResponse response) {
					// response.getStatusLine().getStatusCode()でレスポンスコードを判定する。
					// 正常に通信できた場合、HttpStatus.SC_OK（HTTP 200）となる。
					switch (response.getStatusLine().getStatusCode()) {
					case HttpStatus.SC_OK:
						// レスポンスデータを文字列として取得する。
						// byte[]として読み出したいときはEntityUtils.toByteArray()を使う。
						try {
							return EntityUtils.toString(response.getEntity(),
									"UTF-8");
						} catch (ParseException e) {
						} catch (IOException e) {
						}

					case HttpStatus.SC_NOT_FOUND:
						Log.d("luciferblue", "データないよ！");

					default:
						Log.d("luciferblue", "なんか通信エラーでた");
					}
					return null;
				}
			});

			// // logcatにレスポンスを表示
			// Log.d("luciferblue", "Result: " + result);
		} catch (ClientProtocolException e) {
		} catch (IOException e) {
		} finally {
			// ここではfinallyでshutdown()しているが、HttpClientを使い回す場合は、
			// 適切なところで行うこと。当然だがshutdown()したインスタンスは通信できなくなる。
			httpClient.getConnectionManager().shutdown();
		}
	}

	private void registerData() {
		String ht = "imaocande-test";
		long ct = getThread().countList.size();
		Time time = new Time();
		time.set(System.currentTimeMillis());
		String dt = time.format("%Y-%m-%dT%H:%M+09:00");
		String la = "";
		String lg = "";
		if (lastLocation != null) {
			la = Double.toString(lastLocation.getLatitude());
			lg = Double.toString(lastLocation.getLongitude());
		}

		try {
			JSONObject json = new JSONObject();
			json.put("ht", ht);
			json.put("sn", sn);
			json.put("ct", ct);
			json.put("dt", dt);
			json.put("la", la);
			json.put("lg", lg);

			Log.d("luciferblue", "JSON: " + json.toString());
			sn++;
			if (sn > 9999) {
				sn = 1;
			}

			appendToLog(json.toString());
			sendDataToServer(json.toString());
		} catch (JSONException e) {
		}
	}

	public void onLocationChanged(Location location) {
		lastLocation = location;
	}

	public void onProviderDisabled(String provider) {
	}

	public void onProviderEnabled(String provider) {
	}

	public void onStatusChanged(String provider, int status, Bundle extras) {
	}
}
